import {
  getPositionModel,
  addPositionModel,
  updatePositionModel,
  removePositionModel,
  topoDiscoverMapper,
  topoDiscoverMapperSystem
} from '@/api/mapper'
import { mapGetters, mapActions, mapMutations } from 'vuex'
import 'vis/dist/vis.min.css'

export default {
  computed: {
    ...mapGetters('d2admin', {
      asideMenu: 'menu/asideMenu'
    })
  },
  data () {
    return {
      width: 1000, // 默认宽度
      sessionId: '',
      cmdTimestamp: '',
      isLoading: false, // 是否正在加载数据
      dialogFormVisible: false, //修改对话框
      centerDialogVisible: false, // 删除对话框
      openSystemIds: [], // 点开应用系统id暂存
      nodesPosition: [], // 应用系统云图初始位置及点开位置预存 [{id: xx, open:0, within:[], without:[]}]
      stabilizedNodes: [], // 结构稳定后,整个图数据结构
      withinRemoveEdges: [], // 因云图打开被删除的云图到云图的连线暂存
      withoutRemoveEdges: [] // 因云图打开被删除的节点到云图的连线暂存
    }
  },
  methods: {
    ...mapMutations('d2admin/page', [
      'keepAlivePush', // 页面缓存
      'keepAliveRemove' // 清除页面缓存
    ]),
    ...mapActions('d2admin/page', [
      'close' // 关闭tab页
    ]),
    /**
     * [drawTopo 画图公共方法]
     * @param  {[type]} snapData [图例数据]
     * @param  {[type]} topoId   [dom id]
     * @return {[type]}          []
     */
    drawTopo(snapData, topoId){
      let moment = require('moment');
      let DataSet = require('vis/lib/DataSet');
      let Network = require('vis/lib/network/Network');
      let container = document.getElementById(topoId);
      let nodes = new DataSet([]);
      let edges = new DataSet([]);
      let data = {
        nodes: nodes,
        edges: edges
      };
      let options = {
        layout: {
          improvedLayout: true,
          randomSeed: 6
        },
        nodes: {
          shape: 'dot',
          size: 20,
          font: {
            size: 20,
            color: '#ffffff'
          },
          borderWidth: 2
        },
        edges: {
          smooth: false
        },
        physics: {
          enabled: false
        }
      };
      let network = new Network(container, data, options);
      // network.setSize(this.width, this.width)
      this.sessionId = snapData.sessionId
      this.cmdTimestamp = snapData.cmdTimestamp
      this.nodesPosition = []
      let l = snapData.systems.length
      snapData.systems.forEach((system, i) => {
        let r = this.width * l / 120
        let degress = 360 * i / l;
        let a = Math.sin(degress * Math.PI / 180) * r;
        let b = Math.cos(degress * Math.PI / 180) * r;
        if (system.x !== undefined) {
          a = system.x
          b = system.y
        }
        let nodeIsOpen = this.openSystemIds.findIndex(id => {
          return id == system.id
        })
        if (nodeIsOpen > -1) {
          this.nodesPosition.push({
            id: system.id,
            open: 0,
            within: [a / 3, b / 3],
            without: [a, b]
          })
        } else {
          this.nodesPosition.push({
            id: system.id,
            open: 0,
            within: [a, b],
            without: [a * 3, b * 3]
          })
        }
        nodes.add({
          id: system.id,
          label: system.name,
          shape: 'icon',
          x: a,
          y: b,
          icon: {
            face: 'FontAwesome',
            code: '\uf0c2',
            size: 60,
            color: '#229EF4'
          },
          font: {
            color: '#229EF4'
          }
        })
      })
      if (snapData.ips.length > 0) {
        this.openSystemIds.forEach((systemId) => {
          let color = '#' + Math.floor(Math.random() * 16777215).toString(16);
          nodes.update({
            id: systemId,
            icon: {
              color: color
            },
            font: {
              color: color
            }
          });
          snapData.ips.forEach((ip, i) => {
            if (ip.systemId == systemId) {
              nodes.add({
                id: ip.id,
                label: ip.name,
                title: '端口：' + ip.ports.join(','),
                x: ip.x,
                y: ip.y,
                size: 20,
                color: color,
                font: {
                  color: color
                }
              });
            }
          })
        })
      }
      snapData.lines.forEach(line => {
        let title = ''
        line.targetPorts.forEach((port) => {
          title += line.sourceName + ' -> ' + port + '<br/>'
        })
        edges.add({
          id: 'line' + line.source + '-' + line.target,
          from: line.source,
          to: line.target,
          title: title,
          arrows: 'to',
          color: '#229EF4'
        })
      })
      this.isLoading = false
      this.stabilizedNodes = this.objectToArray(network.getPositions());
      let _this = this
      network.on("doubleClick", function(params) {
        _this.isLoading = true
        let systemId = params.nodes[0]
        let nodePosition = _this.nodesPosition.find(function(node) {
          return node.id.toString() == systemId;
        })
        if (nodePosition != undefined) {
          let nodeIsOpen = _this.openSystemIds.findIndex(id => {
            return id == systemId
          })
          if (nodeIsOpen > -1) {
            _this.openSystemIds.splice(nodeIsOpen, 1)
            topoDiscoverMapperSystem({
              systemId: systemId,
              openedSystemId: _this.openSystemIds.join(','),
              eventFlag: 'OPEN'
            }).then(response => {
              response.ips.forEach((ip, i) => {
                nodes.remove({
                  id: ip.id
                });
              })
              response.lines.forEach(line => {
                edges.remove({
                  id: 'line' + line.source + '-' + line.target
                })
              })
            })
            topoDiscoverMapperSystem({
              systemId: systemId,
              openedSystemId: _this.openSystemIds.join(','),
              eventFlag: 'CLOSE'
            }).then(response => {
              nodePosition.open = 0
              nodes.update({
                id: systemId,
                x: nodePosition.within[0],
                y: nodePosition.within[1],
                icon: {
                  color: '#229EF4'
                },
                font: {
                  color: '#229EF4'
                }
              });
              response.lines.forEach(line => {
                edges.add({
                  id: 'line' + line.source + '-' + line.target,
                  // title: line.flow,
                  from: line.source,
                  to: line.target,
                  arrows: 'to',
                  color: {
                    color: '#229EF4'
                  }
                })
              })
              _this.isLoading = false
              _this.stabilizedNodes = _this.objectToArray(network.getPositions());
            })
          } else {
            topoDiscoverMapperSystem({
              systemId: systemId,
              openedSystemId: _this.openSystemIds.join(','),
              eventFlag: 'OPEN'
            }).then(response => {
              let color = '#' + Math.floor(Math.random() * 16777215).toString(16);
              _this.openSystemIds.push(systemId)
              nodePosition.open = 1
              nodes.update({
                id: systemId,
                x: nodePosition.without[0],
                y: nodePosition.without[1],
                icon: {
                  color: color
                },
                font: {
                  color: color
                }
              });
              edges.forEach(edge => {
                if (edge.from == systemId || edge.to == systemId) {
                  edges.remove(edge)
                }
              })
              let l = response.ips.length
              response.ips.forEach((ip, i) => {
                let r = _this.width * l / 60
                let degress = 360 * i / l;
                let a = Math.sin(degress * Math.PI / 180) * r;
                let b = Math.cos(degress * Math.PI / 180) * r;
                nodes.add({
                  id: ip.id,
                  label: ip.name,
                  title: '端口：' + ip.ports.join(','),
                  x: nodePosition.without[0] + a,
                  y: nodePosition.without[1] + b,
                  size: 20,
                  color: color,
                  font: {
                    color: color
                  }
                });
              })
              response.lines.forEach(line => {
                let title = ''
                line.targetPorts.forEach((port) => {
                  title += line.sourceName + ' -> ' + port + '<br/>'
                })
                edges.add({
                  id: 'line' + line.source + '-' + line.target,
                  title: title,
                  from: line.source,
                  to: line.target,
                  arrows: 'to',
                  color: {
                    color: color
                  },
                  font: {
                    color: color
                  }
                })
              })
              _this.isLoading = false
              _this.stabilizedNodes = _this.objectToArray(network.getPositions());
            })
          }
        }
      });
      network.on("click", function(params){
        _this.stabilizedNodes = _this.objectToArray(network.getPositions());
      })
      network.on("dragEnd", function (params) {
        let nodeIsOpen = _this.openSystemIds.findIndex(id => {
          return id == params.nodes[0]
        })
        if (nodeIsOpen === -1) {
          let nodePosition = _this.nodesPosition.find(function(node) {
            return node.id.toString() == params.nodes[0];
          })
          if (nodePosition != undefined) {
            nodePosition.within = [params.pointer.canvas.x, params.pointer.canvas.y]
            nodePosition.without = [params.pointer.canvas.x * 3, params.pointer.canvas.y * 3]
          }
        }
      })
      network.on("zoom", function (params) {
        // console.log(JSON.stringify(params, null, 4))
      });
    },
    /**
     * [addPosition 保存快照]
     * @param {[type]} description [快照描述]
     */
    addPosition(description) {
      if (this.stabilizedNodes === [] || this.stabilizedNodes.length < 1) {
        this.$message({
          message: '快照保存出错!请刷新页面重试',
          type: 'error'
        });
        return
      }
      let params = {
        nodePositions: this.stabilizedNodes,
        openedSystemId: this.openSystemIds.join(','),
        cmdTimestamp: this.cmdTimestamp,
        sessionId: this.sessionId,
        description: description
      }
      addPositionModel(params).then(res=>{
        this.$message({
          message: '快照保存成功',
          type: 'success'
        });
        this.dialogFormVisible = false
        this.snapshotToMenu()
      })
    },
    /**
     * [editPosition 修改快照]
     * @param  {[type]} data [快照编号和描述]
     * @return {[type]}      [description]
     */
    editPosition(data) {
      let params = {
        modelId: data.id,
        nodePositions: this.stabilizedNodes,
        description: data.description,
        openedSystemId: this.openSystemIds.join(',')
      }
      updatePositionModel(params).then(res=>{
        this.$message({
          message: '快照更新成功',
          type: 'success'
        })
        this.dialogFormVisible = false
        this.snapshotToMenu()
      })
    },
    /**
     * [removePosition 删除快照]
     * @param  {[type]} data [快照编号]
     * @return {[type]}      [description]
     */
    removePosition(data){
      removePositionModel({modelId: data.id}).then(res => {
        this.$message({
          message: '删除成功',
          type: 'success'
        })
        this.close({
          tagName: 'snapshot',
          vm: this
        })
        this.centerDialogVisible = false
        this.snapshotToMenu()
      })
    },
    /**
     * [snapshotToMenu 加载快照列表为左侧菜单]
     * @return {[type]} [description]
     */
    snapshotToMenu() {
      getPositionModel().then(res => {
        // 设置侧边栏菜单
        this.$store.commit('d2admin/menu/asideSet', [{ path: '/index', title: '首页', icon: 'home' }])
        res.forEach(position => {
          this.asideMenu.push({
            icon: 'retweet',
            path: '/mapper/snapshot/' + position.id,
            title: position.description
          })
        })
      })
    },
    /**
     * [objectToArray 图表数据处理]
     * @param  {[type]} obj [数据对象]
     * @return {[type]}     [格式化后数据]
     */
    objectToArray(obj) {
      return Object.keys(obj).map(key => {
        obj[key].id = key;
        return obj[key];
      });
    }
  },
  mounted() {
    this.width = window.innerWidth
    this.snapshotToMenu()
  }
}